home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / db / esm-3.1 / esm-3 / usr / local / sm / src / serverlib / redo / redoPageDeallocation.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-05  |  11.1 KB  |  399 lines

  1. /*
  2.  *   $RCSfile: redoPageDeallocation.c,v $  
  3.  *   $Revision: 1.1.1.1 $  
  4.  *   $Date: 1996/05/04 21:55:57 $      
  5.  */ 
  6. /**********************************************************************
  7. * EXODUS Database Toolkit Software
  8. * Copyright (c) 1991 Computer Sciences Department, University of
  9. *                    Wisconsin -- Madison
  10. * All Rights Reserved.
  11. *
  12. * Permission to use, copy, modify and distribute this software and its
  13. * documentation is hereby granted, provided that both the copyright
  14. * notice and this permission notice appear in all copies of the
  15. * software, derivative works or modified versions, and any portions
  16. * thereof, and that both notices appear in supporting documentation.
  17. *
  18. * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
  19. * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.  
  20. * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  21. * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  22. *
  23. * The EXODUS Project Group requests users of this software to return 
  24. * any improvements or extensions that they make to:
  25. *
  26. *   EXODUS Project Group 
  27. *     c/o David J. DeWitt and Michael J. Carey
  28. *   Computer Sciences Department
  29. *   University of Wisconsin -- Madison
  30. *   Madison, WI 53706
  31. *
  32. *     or exodus@cs.wisc.edu
  33. *
  34. * In addition, the EXODUS Project Group requests that users grant the 
  35. * Computer Sciences Department rights to redistribute these changes.
  36. **********************************************************************/
  37.  
  38.  
  39. #include "sysdefs.h"
  40. #include "ess.h"
  41. #include "checking.h"
  42. #include "trace.h"
  43. #include "error.h"
  44. #include "list.h"
  45. #include "pool.h"
  46. #include "tid.h"
  47. #include "io.h"
  48. #include "lock.h"
  49. #include "object.h"
  50. #include "msgdefs.h"
  51. #include "thread.h"
  52. #include "latch.h"
  53. #include "semaphore.h"
  54. #include "link.h"
  55. #include "lsn.h"
  56. #include "bf.h"
  57. #include "log.h"
  58. #include "volume.h"
  59. #include "logrecs.h"
  60. #include "trans.h"
  61. #include "bitmap.h"
  62. #include "openlog.h"
  63. #include "logaction.h"
  64. #include "io_extfuncs.h"
  65. #include "io_logfuncs.h"
  66. #include "bf_extfuncs.h"
  67. #include "bm_extfuncs.h"
  68. #include "trans_extfuncs.h"
  69. #include "redo_extfuncs.h"
  70. #include "util_funcs.h"
  71. #include "thread_globals.h"
  72. #include "log_globals.h"
  73. #include "log_extfuncs.h"
  74. #include "distr.h"
  75. #include "distr_globals.h"
  76. #include "distr_extfuncs.h"
  77.  
  78.  
  79.  void
  80. redoPageDeallocation (
  81.  
  82.     LOGRECORDHDR            *record 
  83. )
  84. {
  85.  
  86.     register VOLREC            *volRec;
  87.     register PID            *pid;
  88.     register int            i;    
  89.     register GROUPLINK        *groupLink;
  90.     register DIRTYPAGEINFO    *dirtyInfo;
  91.     BITMAPPAGE                *bitmapPage;
  92.     PID                        bitmapPid;
  93.     PID                        volHdrPid;
  94.     LRC                     *lrcList;
  95.     int                     bitmapPageCount;
  96.     int                     deallocPageCount; /* # of pages allocated */
  97.     LRC                     *headerLRC;     /* volume header lrc    */
  98.     SHORTPID                allocPage;
  99.     int                     bitsToSet;      /* # bits to set on page*/
  100.     int                        totalBitsToSet;
  101.     int                        bitsSetSoFar;
  102.     int                     bit;
  103.     PAGEALLOCINFO           *pageAllocInfo;
  104.     TRANSREC                *transRec;
  105.  
  106.  
  107.     TRPRINT(TR_IO|TR_LOG, TR_LEVEL_1, ("lsn:%d", record->recordLSN.offset));
  108.  
  109.     /*
  110.      *    Initially the volume info is unknown
  111.      */
  112.     volRec = NULL;
  113.  
  114.     /*
  115.      *    get a pointer to the common page deallocation info
  116.      */
  117.     pageAllocInfo = (PAGEALLOCINFO *) GET_LOG_IMAGE(record, 0);
  118.     TRPRINT(TR_IO|TR_LOG, TR_LEVEL_2, ("numPages:%d", pageAllocInfo->numPages));
  119.  
  120.     /*
  121.      *    get a pointer to the name in the record and the number
  122.      *    of pages allocated
  123.      */
  124.     pid = (PID *) GET_LOG_IMAGE(record, 1);
  125.     deallocPageCount = GET_LOG_IMAGE_SIZE(record, 1) / sizeof(PID);
  126.     SM_ASSERT(LEVEL_3, pageAllocInfo->numPages == deallocPageCount);
  127.     TRPRINT(TR_IO|TR_LOG, TR_LEVEL_2, ("pid:%d", pid->page));
  128.  
  129.     /*
  130.      *    - for distr trans
  131.      *    check if the transaction is one which is in prepared state
  132.      */
  133.     if ((transRec = findDistrTransRec(record->tid, &ServerDistrTransList)) != NULL)    {
  134.         /*
  135.          *    just reconstruct the list - don't do the deallocation
  136.          *    NOTE: pass in PAGE_GENERIC as the type because 
  137.          *          io_FakeDeallocPages converts slotted pages to
  138.          *          normal ones - we don't want to do this here
  139.          *          because we would already have done that when
  140.          *          we encountered the log record for the conversion
  141.          */
  142.         if (io_FakeDeallocPages(pageAllocInfo->page2size,
  143.                                 pageAllocInfo->numPages,
  144.                                 pid,
  145.                                 &(transRec->pageDeallocList),
  146.                                 PAGE_GENERIC) != esmNOERROR) {
  147.  
  148.             SM_ERROR(TYPE_FATAL, esmINTERNAL);
  149.         }
  150.  
  151.         /*
  152.          *    return success
  153.          */
  154.         return;
  155.     }
  156.  
  157.     /*
  158.      *  get a pointer to the lrc list for the bitmap pages, and
  159.      *  calculate the number of bitmap pages involved, base on
  160.      *  the length of the list
  161.      */
  162.     lrcList = (LRC *) GET_LOG_IMAGE(record, 2);
  163.     bitmapPageCount = GET_LOG_IMAGE_SIZE(record, 2) / sizeof(LRC);
  164.     TRPRINT(TR_RECOVER, TR_LEVEL_2, ("lrc list size:%d", bitmapPageCount));
  165.  
  166.     /*
  167.      *    get a pointer to the volume header lrc
  168.      */
  169.     headerLRC = &(pageAllocInfo->headerLRC);
  170.     TRPRINT(TR_RECOVER, TR_LEVEL_2, ("header lrc:%d", headerLRC->count));
  171.  
  172.     /*
  173.      *    Remove all the dealloced pages from the buffer pool
  174.      */
  175.     for (i = 0; i < deallocPageCount; i++) {
  176.         bf_InvalidatePage(pid+i);
  177.     }
  178.  
  179.     /*
  180.      *    set the volume id of the bitmap pid
  181.      */
  182.     bitmapPid.volid = pid->volid;
  183.  
  184.     /*
  185.      *    check the pages for the dirty list
  186.      */
  187.     allocPage = pid->page;  /* first allocated page */
  188.     totalBitsToSet = deallocPageCount * BLOCKCOUNT(pageAllocInfo->page2size);
  189.     bitsSetSoFar = 0;
  190.     for (i = 0; i < bitmapPageCount; i++)    {
  191.  
  192.         /*
  193.          *    calculate the bitmap page
  194.          */
  195.         bitmapPid.page = BIT_TO_PAGE(allocPage) + pageAllocInfo->firstBitmapPage;
  196.         TRPRINT(TR_RECOVER, TR_LEVEL_2, ("bitmap page:%d", bitmapPid.page));
  197.  
  198.         /*
  199.          *  The number of bits to set is either the number left on
  200.          *  the bitmap page or the number of pages left to mark
  201.          *  allocated, whichever is smaller.
  202.          */
  203.         bitsToSet = (int) MIN((BITS_IN_PAGE - BIT_IN_PAGE(allocPage)),
  204.                         (totalBitsToSet - bitsSetSoFar) );
  205.         bitsSetSoFar += bitsToSet;
  206.         SM_ASSERT(LEVEL_3, deallocPageCount >= (allocPage - pid->page));
  207.  
  208.         /*
  209.          *    check to see if the page is in the dirty list
  210.          */
  211.         if ((dirtyInfo = searchDirtyPageTable( &bitmapPid )) == NULL)    {
  212.  
  213.             /*
  214.              *    don't need to redo the entry
  215.              */
  216.             TRPRINT(TR_RECOVER, TR_LEVEL_2, ("page not in table"));
  217.             continue;
  218.         }
  219.  
  220.         /*
  221.          *  check to see if the lrc on the page is greater than
  222.          *  the lrc in the log record
  223.          */
  224.         if (CHECK_PAGE_LRC_LESS_DIRTYINFO(lrcList[i], record->recordLSN, dirtyInfo)) {
  225.             /*
  226.              *    don't need to redo
  227.              */
  228.             TRPRINT(TR_RECOVER, TR_LEVEL_2, ("dirty info page lrc later"));
  229.             continue;
  230.         }
  231.  
  232.         /*
  233.          *    check to see if the volume is mounted
  234.          */
  235.         if (volRec == NULL) {
  236.             if ((volRec = io_FindVolRec(pid->volid)) == NULL)    {
  237.  
  238.                 SM_ERROR(TYPE_FATAL, Active->errno);
  239.             }
  240.             SM_ASSERT(LEVEL_3, pageAllocInfo->firstBitmapPage == volRec->header->freeBitmapAddr);
  241.         }
  242.  
  243.         /*
  244.          *    read in the page
  245.          */
  246.         if ((groupLink = bf_ReadPage(volRec->bufGroup, &bitmapPid,
  247.                                      BITMAP_PAGE2SIZE, BF_SEM)) == NULL)    {
  248.  
  249.             SM_ERROR(TYPE_FATAL, esmINTERNAL);
  250.         }
  251.  
  252.         /*
  253.          *    get a pointer to the bitmap page
  254.          */
  255.         bitmapPage = (BITMAPPAGE *) groupLink->bufFrame;
  256.  
  257.         /*
  258.          *  check to see if the lrc on the page is greater than
  259.          *  the lrc in the log record
  260.          */
  261.         if (compareLRC( &(lrcList[i]), &(bitmapPage->lrc)) <= 0)    {
  262.  
  263.             /*
  264.              *  don't need to redo
  265.              *  mark the page lrc
  266.              */
  267.             TRPRINT(TR_RECOVER, TR_LEVEL_2, ("actual page lrc later"));
  268.             dirtyInfo->lrc = bitmapPage->lrc;
  269.  
  270.             /*
  271.              *    release the page, not dirty
  272.              */
  273.             signalSemaphore( &(groupLink->pageHash->semaphore) );
  274.             bf_UnfixPage(groupLink, BF_DEFAULT, FALSE);
  275.             continue;
  276.         }
  277.  
  278.         /*
  279.          *  clear all necessary bits for this bitmap page
  280.          */
  281.         for (bit = (int) BIT_IN_PAGE(allocPage);
  282.              bit < (BIT_IN_PAGE(allocPage)+bitsToSet); bit++) {
  283.  
  284.             /*
  285.              *  actually set the bit
  286.              */
  287.             bm_SetBit((UFOUR *) groupLink->bufFrame, (FOUR) BIT_IN_PAGE(bit));
  288.         }
  289.  
  290.         /*
  291.          *  set the page lrc
  292.          *    Set up the firstLSN/LRC for the page
  293.          */
  294.         bitmapPage->lrc = lrcList[i];
  295.         DEPEND_LOG(groupLink->pageHash, 0, &(record->recordLSN), (lrcList+i));
  296.         TRPRINT(TR_RECOVER, TR_LEVEL_2, ("marking new page lrc:%d", bitmapPage->lrc.count));
  297.  
  298.         /* 
  299.          *    free and dirty the page
  300.          */
  301.         signalSemaphore( &(groupLink->pageHash->semaphore) );
  302.         bf_UnfixPage(groupLink, BF_DEFAULT, TRUE);
  303.  
  304.         /*
  305.          *  Calculate index of the first allocated page on the next
  306.          *  bitmap page.
  307.          */
  308.         allocPage += BITS_IN_PAGE - BIT_IN_PAGE(allocPage);
  309.     }
  310.     SM_ASSERT(LEVEL_3, totalBitsToSet == bitsSetSoFar);
  311.  
  312.     /*
  313.      *  Redo the increment to the numFreePages field on the volume
  314.      *  header if necessary.  First, get the header page pid.
  315.      */
  316.     volHdrPid.page = HEADERADDR;
  317.     volHdrPid.volid = pid->volid;
  318.  
  319.     /*
  320.      *  check to see if the page is in the dirty page list
  321.      */
  322.     if ((dirtyInfo = searchDirtyPageTable(&volHdrPid)) == NULL)    {
  323.  
  324.         /*
  325.          *  don't need to redo
  326.          */
  327.         TRPRINT(TR_RECOVER, TR_LEVEL_2, ("dirty page not present"));
  328.         return;
  329.     }
  330.  
  331.     if (volRec == NULL)  {
  332.         if ((volRec = io_FindVolRec(volHdrPid.volid)) == NULL)    {
  333.  
  334.             SM_ERROR(TYPE_FATAL, Active->errno);
  335.         }
  336.         SM_ASSERT(LEVEL_3, pageAllocInfo->firstBitmapPage == volRec->header->freeBitmapAddr);
  337.     }
  338.  
  339. #ifdef DEBUG
  340.     /*
  341.      *  check to see if the lrc on the page is greater than
  342.      *  the lrc in the log record
  343.      *  NOTE: this comparison is not strictly necessary, since the
  344.      *  header page is always resident and the next comparison
  345.      *  count be made instead.
  346.      */
  347.     if (compareLRC( headerLRC, &(dirtyInfo->lrc) ) < 0)  {
  348.  
  349.         /*
  350.          *  don't need to redo
  351.          */
  352.         TRPRINT(TR_RECOVER, TR_LEVEL_2, ("dirty info page lrc later"));
  353.         return;
  354.     }
  355.  
  356.     /*
  357.      *  Make sure the comparison was correct
  358.      */
  359.     SM_ASSERT(LEVEL_3, compareLSN( &(record->recordLSN), &(dirtyInfo->lsn)) >= 0);
  360. #endif DEBUG
  361.  
  362.     /*
  363.      *  check to see if the lrc on the header page is greater than
  364.      *  the lrc in the log record
  365.      */
  366.     if (compareLRC( headerLRC, &volRec->header->lrc) <= 0)    {
  367.  
  368.         /*
  369.          *  don't need to redo
  370.          *  mark the page lrc, and return
  371.          */
  372.         TRPRINT(TR_RECOVER, TR_LEVEL_2, ("actual page lrc later"));
  373.         dirtyInfo->lrc = volRec->header->lrc;
  374.  
  375.         return;
  376.     }
  377.  
  378.     /*
  379.      *  The volume header needs to be updated, so increment the number
  380.      *  of free pages by the number deallocated.
  381.      */
  382.     if (waitSemaphore(&(volRec->headerLink->pageHash->semaphore)) != esmNOERROR) {
  383.         SM_ERROR(TYPE_FATAL, esmNOERROR);
  384.     }
  385.     io_ChangeVolFreePages(volRec, totalBitsToSet);
  386.  
  387.     /*
  388.      *  mark the LRC on the header page and dirty the page
  389.      *    Set up the firstLSN/LRC for the page
  390.      *    release the semaphore on the volume header
  391.      */
  392.     volRec->header->lrc = *headerLRC;
  393.     DEPEND_LOG(volRec->headerLink->pageHash, 0, &(record->recordLSN), headerLRC);
  394.     TRPRINT(TR_RECOVER, TR_LEVEL_2, ("marking header page lrc:%d", volRec->header->lrc.count));
  395.     signalSemaphore(&(volRec->headerLink->pageHash->semaphore));
  396.  
  397.     return;
  398. }
  399.